package com.bi.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bi.entity.ThemeScenario;
import com.bi.entity.ThemeScenarioComponent;
import com.bi.entity.ThemeScenarioTemplate;
import com.bi.mapper.ThemeScenarioMapper;
import com.bi.service.ThemeScenarioService;
import com.bi.service.ThemeScenarioComponentService;
import com.bi.service.ThemeScenarioTemplateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 主题分析场景服务实现类
 * 
 * @author BI Platform Team
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ThemeScenarioServiceImpl extends ServiceImpl<ThemeScenarioMapper, ThemeScenario> implements ThemeScenarioService {

    private final ThemeScenarioComponentService componentService;
    private final ThemeScenarioTemplateService templateService;
    
    /**
     * 重写 getBaseMapper 方法以解决 MyBatis-Plus 3.5.x 版本返回类型不兼容问题
     */
    @Override
    public ThemeScenarioMapper getBaseMapper() {
        return super.getBaseMapper();
    }

    @Override
    public IPage<ThemeScenario> getThemeScenarioPage(long current, long size, Map<String, Object> params) {
        Page<ThemeScenario> page = new Page<>(current, size);
        return baseMapper.selectThemeScenarioPage(page, params);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createThemeScenario(ThemeScenario themeScenario, List<ThemeScenarioComponent> components) {
        try {
            // 设置创建信息
            themeScenario.setCreateTime(LocalDateTime.now());
            themeScenario.setUpdateTime(LocalDateTime.now());
            themeScenario.setStatus(ThemeScenario.ScenarioStatus.DRAFT);
            themeScenario.setAccessCount(0);
            themeScenario.setRating(0.0);
            
            // 生成访问路径
            String accessPath = generateAccessPath(null);
            themeScenario.setAccessPath(accessPath);
            
            // 保存场景
            boolean saveResult = save(themeScenario);
            if (!saveResult) {
                throw new RuntimeException("保存主题场景失败");
            }
            
            // 保存组件
            if (components != null && !components.isEmpty()) {
                for (ThemeScenarioComponent component : components) {
                    component.setScenarioId(themeScenario.getId());
                    component.setCreateTime(LocalDateTime.now());
                    component.setUpdateTime(LocalDateTime.now());
                }
                boolean componentsResult = componentService.saveBatch(components);
                if (!componentsResult) {
                    throw new RuntimeException("保存场景组件失败");
                }
            }
            
            log.info("创建主题场景成功: id={}, name={}", themeScenario.getId(), themeScenario.getName());
            return true;

        } catch (Exception e) {
            log.error("创建主题场景失败: name={}, error={}", themeScenario.getName(), e.getMessage());
            throw new RuntimeException("创建主题场景失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateThemeScenario(ThemeScenario themeScenario, List<ThemeScenarioComponent> components) {
        try {
            // 更新场景信息
            themeScenario.setUpdateTime(LocalDateTime.now());
            boolean updateResult = updateById(themeScenario);
            if (!updateResult) {
                throw new RuntimeException("更新主题场景失败");
            }
            
            // 删除原有组件
            componentService.removeByScenarioId(themeScenario.getId());
            
            // 保存新组件
            if (components != null && !components.isEmpty()) {
                for (ThemeScenarioComponent component : components) {
                    component.setScenarioId(themeScenario.getId());
                    component.setCreateTime(LocalDateTime.now());
                    component.setUpdateTime(LocalDateTime.now());
                }
                boolean componentsResult = componentService.saveBatch(components);
                if (!componentsResult) {
                    throw new RuntimeException("保存场景组件失败");
                }
            }
            
            log.info("更新主题场景成功: id={}, name={}", themeScenario.getId(), themeScenario.getName());
            return true;

        } catch (Exception e) {
            log.error("更新主题场景失败: id={}, error={}", themeScenario.getId(), e.getMessage());
            throw new RuntimeException("更新主题场景失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteThemeScenario(Long scenarioId) {
        try {
            // 删除场景组件
            componentService.removeByScenarioId(scenarioId);
            
            // 软删除场景
            ThemeScenario scenario = getById(scenarioId);
            if (scenario == null) {
                throw new RuntimeException("主题场景不存在");
            }
            
            scenario.setStatus(ThemeScenario.ScenarioStatus.DELETED);
            scenario.setUpdateTime(LocalDateTime.now());
            boolean deleteResult = updateById(scenario);
            
            log.info("删除主题场景成功: id={}", scenarioId);
            return deleteResult;

        } catch (Exception e) {
            log.error("删除主题场景失败: id={}, error={}", scenarioId, e.getMessage());
            throw new RuntimeException("删除主题场景失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ThemeScenario copyThemeScenario(Long sourceScenarioId, String newName) {
        try {
            ThemeScenario sourceScenario = getById(sourceScenarioId);
            if (sourceScenario == null) {
                throw new RuntimeException("源主题场景不存在");
            }
            
            // 复制场景
            ThemeScenario newScenario = new ThemeScenario();
            newScenario.setName(newName);
            newScenario.setDisplayName(newName);
            newScenario.setDescription(sourceScenario.getDescription() + " (副本)");
            newScenario.setScenarioType(sourceScenario.getScenarioType());
            newScenario.setApplicationType(sourceScenario.getApplicationType());
            newScenario.setTemplateId(sourceScenario.getTemplateId());
            newScenario.setTemplateName(sourceScenario.getTemplateName());
            newScenario.setLayoutConfig(sourceScenario.getLayoutConfig());
            newScenario.setThemeConfig(sourceScenario.getThemeConfig());
            newScenario.setStyleConfig(sourceScenario.getStyleConfig());
            newScenario.setDataConfig(sourceScenario.getDataConfig());
            newScenario.setCacheConfig(sourceScenario.getCacheConfig());
            newScenario.setRefreshConfig(sourceScenario.getRefreshConfig());
            newScenario.setPermissionConfig(sourceScenario.getPermissionConfig());
            newScenario.setIsPublic(false);
            newScenario.setIsRecommended(false);
            newScenario.setAccessCount(0);
            newScenario.setRating(0.0);
            newScenario.setTags(sourceScenario.getTags());
            newScenario.setStatus(ThemeScenario.ScenarioStatus.DRAFT);
            newScenario.setCreator("current_user");
            
            // 生成新的访问路径
            String accessPath = generateAccessPath(null);
            newScenario.setAccessPath(accessPath);
            
            boolean saveResult = save(newScenario);
            if (!saveResult) {
                throw new RuntimeException("保存复制的场景失败");
            }
            
            // 复制组件
            List<ThemeScenarioComponent> sourceComponents = componentService.getByScenarioId(sourceScenarioId);
            if (!sourceComponents.isEmpty()) {
                for (ThemeScenarioComponent component : sourceComponents) {
                    component.setId(null);
                    component.setScenarioId(newScenario.getId());
                    component.setCreateTime(LocalDateTime.now());
                    component.setUpdateTime(LocalDateTime.now());
                }
                componentService.saveBatch(sourceComponents);
            }
            
            log.info("复制主题场景成功: sourceId={}, newId={}, newName={}", sourceScenarioId, newScenario.getId(), newName);
            return newScenario;

        } catch (Exception e) {
            log.error("复制主题场景失败: sourceId={}, newName={}, error={}", sourceScenarioId, newName, e.getMessage());
            throw new RuntimeException("复制主题场景失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publishThemeScenario(Long scenarioId) {
        try {
            ThemeScenario scenario = getById(scenarioId);
            if (scenario == null) {
                throw new RuntimeException("主题场景不存在");
            }
            
            scenario.setStatus(ThemeScenario.ScenarioStatus.PUBLISHED);
            scenario.setPublishTime(LocalDateTime.now());
            scenario.setUpdateTime(LocalDateTime.now());
            
            boolean updateResult = updateById(scenario);
            log.info("发布主题场景成功: id={}", scenarioId);
            return updateResult;

        } catch (Exception e) {
            log.error("发布主题场景失败: id={}, error={}", scenarioId, e.getMessage());
            throw new RuntimeException("发布主题场景失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean archiveThemeScenario(Long scenarioId) {
        try {
            ThemeScenario scenario = getById(scenarioId);
            if (scenario == null) {
                throw new RuntimeException("主题场景不存在");
            }
            
            scenario.setStatus(ThemeScenario.ScenarioStatus.ARCHIVED);
            scenario.setUpdateTime(LocalDateTime.now());
            
            boolean updateResult = updateById(scenario);
            log.info("归档主题场景成功: id={}", scenarioId);
            return updateResult;

        } catch (Exception e) {
            log.error("归档主题场景失败: id={}, error={}", scenarioId, e.getMessage());
            return false;
        }
    }

    @Override
    public List<ThemeScenarioComponent> getScenarioComponents(Long scenarioId) {
        return componentService.getByScenarioId(scenarioId);
    }

    @Override
    public List<ThemeScenarioComponent> getScenarioComponentTree(Long scenarioId) {
        return componentService.getComponentTree(scenarioId);
    }

    @Override
    public boolean addScenarioComponent(ThemeScenarioComponent component) {
        component.setCreateTime(LocalDateTime.now());
        component.setUpdateTime(LocalDateTime.now());
        return componentService.save(component);
    }

    @Override
    public boolean updateScenarioComponent(ThemeScenarioComponent component) {
        component.setUpdateTime(LocalDateTime.now());
        return componentService.updateById(component);
    }

    @Override
    public boolean removeScenarioComponent(Long componentId) {
        return componentService.removeById(componentId);
    }

    @Override
    public boolean updateComponentOrder(List<ThemeScenarioComponent> components) {
        return componentService.updateBatchOrder(components);
    }

    @Override
    public boolean updateComponentPosition(Long componentId, String positionConfig) {
        return componentService.updatePosition(componentId, positionConfig);
    }

    @Override
    public boolean updateComponentZIndex(Long componentId, Integer zIndex) {
        return componentService.updateZIndex(componentId, zIndex);
    }

    @Override
    public List<ThemeScenario> getByScenarioType(String scenarioType) {
        return baseMapper.selectByScenarioType(scenarioType);
    }

    @Override
    public List<ThemeScenario> getByApplicationType(String applicationType) {
        return baseMapper.selectByApplicationType(applicationType);
    }

    @Override
    public List<ThemeScenario> searchThemeScenarios(String keyword, String scenarioType, String applicationType) {
        return baseMapper.searchThemeScenarios(keyword, scenarioType, applicationType);
    }

    @Override
    public List<ThemeScenario> getRecommendedScenarios(Integer limit) {
        return baseMapper.selectRecommendedScenarios(limit != null ? limit : 10);
    }

    @Override
    public List<ThemeScenario> getPopularScenarios(Integer limit) {
        return baseMapper.selectPopularScenarios(limit != null ? limit : 10);
    }

    @Override
    public List<ThemeScenario> getMyScenarios(String creator) {
        return baseMapper.selectByCreator(creator);
    }

    @Override
    public Map<String, Object> getScenarioStatistics() {
        return baseMapper.selectScenarioStatistics();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean accessScenario(Long scenarioId) {
        try {
            int updateResult = baseMapper.incrementAccessCount(scenarioId);
            return updateResult > 0;
        } catch (Exception e) {
            log.error("更新场景访问次数失败: scenarioId={}, error={}", scenarioId, e.getMessage());
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean rateScenario(Long scenarioId, Double rating) {
        try {
            int updateResult = baseMapper.updateRating(scenarioId, rating);
            return updateResult > 0;
        } catch (Exception e) {
            log.error("更新场景评分失败: scenarioId={}, rating={}, error={}", scenarioId, rating, e.getMessage());
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ThemeScenario createFromTemplate(Long templateId, String scenarioName, String description) {
        try {
            ThemeScenarioTemplate template = templateService.getById(templateId);
            if (template == null) {
                throw new RuntimeException("模板不存在");
            }
            
            // 从模板创建场景
            ThemeScenario scenario = new ThemeScenario();
            scenario.setName(scenarioName);
            scenario.setDisplayName(scenarioName);
            scenario.setDescription(description);
            scenario.setScenarioType(template.getScenarioType());
            scenario.setApplicationType(template.getApplicationType());
            scenario.setTemplateId(templateId);
            scenario.setTemplateName(template.getDisplayName());
            scenario.setLayoutConfig(template.getDefaultLayoutConfig());
            scenario.setThemeConfig(template.getDefaultThemeConfig());
            scenario.setStyleConfig(template.getDefaultStyleConfig());
            scenario.setComponentsConfig(template.getPresetComponentsConfig());
            scenario.setIsPublic(false);
            scenario.setIsRecommended(false);
            scenario.setAccessCount(0);
            scenario.setRating(0.0);
            scenario.setStatus(ThemeScenario.ScenarioStatus.DRAFT);
            scenario.setCreator("current_user");
            
            // 生成访问路径
            String accessPath = generateAccessPath(null);
            scenario.setAccessPath(accessPath);
            
            boolean saveResult = save(scenario);
            if (!saveResult) {
                throw new RuntimeException("保存场景失败");
            }
            
            // 增加模板使用次数
            templateService.incrementUsageCount(templateId);
            
            log.info("从模板创建场景成功: templateId={}, scenarioId={}", templateId, scenario.getId());
            return scenario;

        } catch (Exception e) {
            log.error("从模板创建场景失败: templateId={}, scenarioName={}, error={}", templateId, scenarioName, e.getMessage());
            throw new RuntimeException("从模板创建场景失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAsTemplate(Long scenarioId, String templateName, String templateDescription) {
        try {
            ThemeScenario scenario = getById(scenarioId);
            if (scenario == null) {
                throw new RuntimeException("主题场景不存在");
            }
            
            // 创建模板
            ThemeScenarioTemplate template = new ThemeScenarioTemplate();
            template.setName(templateName.toLowerCase().replaceAll("\\s+", "_"));
            template.setDisplayName(templateName);
            template.setDescription(templateDescription);
            template.setCategory("自定义模板");
            template.setScenarioType(scenario.getScenarioType());
            template.setApplicationType(scenario.getApplicationType());
            template.setDefaultLayoutConfig(scenario.getLayoutConfig());
            template.setDefaultThemeConfig(scenario.getThemeConfig());
            template.setDefaultStyleConfig(scenario.getStyleConfig());
            template.setPresetComponentsConfig(scenario.getComponentsConfig());
            template.setTemplateConfig("{}");
            template.setIsSystemTemplate(false);
            template.setIsRecommended(false);
            template.setUsageCount(0);
            template.setRating(0.0);
            template.setSortOrder(999);
            template.setStatus(ThemeScenarioTemplate.TemplateStatus.ACTIVE);
            template.setCreator("current_user");
            
            boolean saveResult = templateService.save(template);
            log.info("保存为模板成功: scenarioId={}, templateId={}", scenarioId, template.getId());
            return saveResult;

        } catch (Exception e) {
            log.error("保存为模板失败: scenarioId={}, templateName={}, error={}", scenarioId, templateName, e.getMessage());
            return false;
        }
    }

    @Override
    public Map<String, Object> exportScenario(Long scenarioId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            ThemeScenario scenario = getById(scenarioId);
            if (scenario == null) {
                throw new RuntimeException("主题场景不存在");
            }
            
            List<ThemeScenarioComponent> components = componentService.getByScenarioId(scenarioId);
            
            result.put("success", true);
            result.put("scenario", scenario);
            result.put("components", components);
            result.put("exportTime", LocalDateTime.now());
            result.put("version", "1.0");
            
            log.info("导出场景成功: scenarioId={}", scenarioId);

        } catch (Exception e) {
            log.error("导出场景失败: scenarioId={}, error={}", scenarioId, e.getMessage());
            result.put("success", false);
            result.put("message", "导出失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ThemeScenario importScenario(Map<String, Object> scenarioConfig) {
        try {
            // 简化实现，实际需要解析导入数据
            ThemeScenario scenario = new ThemeScenario();
            scenario.setName("导入的场景_" + System.currentTimeMillis());
            scenario.setDisplayName("导入的场景");
            scenario.setDescription("从外部导入的主题场景");
            scenario.setScenarioType(ThemeScenario.ScenarioType.CUSTOM);
            scenario.setApplicationType(ThemeScenario.ApplicationType.PC);
            scenario.setIsPublic(false);
            scenario.setIsRecommended(false);
            scenario.setAccessCount(0);
            scenario.setRating(0.0);
            scenario.setStatus(ThemeScenario.ScenarioStatus.DRAFT);
            scenario.setCreator("current_user");
            
            // 生成访问路径
            String accessPath = generateAccessPath(null);
            scenario.setAccessPath(accessPath);
            
            boolean saveResult = save(scenario);
            if (saveResult) {
                log.info("导入场景成功: scenarioId={}", scenario.getId());
                return scenario;
            } else {
                throw new RuntimeException("保存导入场景失败");
            }

        } catch (Exception e) {
            log.error("导入场景失败: error={}", e.getMessage(), e);
            throw new RuntimeException("导入场景失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> previewScenario(Long scenarioId) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            ThemeScenario scenario = getById(scenarioId);
            if (scenario == null) {
                throw new RuntimeException("主题场景不存在");
            }
            
            List<ThemeScenarioComponent> components = componentService.getByScenarioId(scenarioId);
            
            result.put("success", true);
            result.put("scenario", scenario);
            result.put("components", components);
            result.put("previewUrl", "/preview/scenario/" + scenarioId);
            
            // 更新访问次数
            accessScenario(scenarioId);

        } catch (Exception e) {
            log.error("预览场景失败: scenarioId={}, error={}", scenarioId, e.getMessage());
            result.put("success", false);
            result.put("message", "预览失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public String generateAccessPath(Long scenarioId) {
        // 生成唯一访问路径
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return "/scenario/" + uuid;
    }
}